//
// Created by johnny.yin on 2017/9/30.
//
#include <android/looper.h>
#include "rocky_server.h"
#include "../utils/connection_utils.h"
#include "./server_thread_pool.h"
#include "../common/rocky_connection.h"
#include "../works/work_data.h"
#include "../utils/app_sys_log.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <sys/select.h>
#include <sys/types.h>

#define DEFAULT_POLL_TIME_MS -1

struct RockyServer{
    int thread_count;
    int server_fd;
    int shutdown;
    size_t buf_size;
    on_connection_disconnected on_disconnected;
    on_received_data on_received;
    ALooper* main_looper;
    ServerThreadPool* thread_pool;
};

RockyServer *rocky_server_create(int thread_count, size_t buf_size, on_received_data on_received,
                                 on_connection_disconnected on_disconnected) {
    int server_fd = socket_local_server("rockysocket", SOCK_STREAM);
    if(server_fd < 0) {
        return NULL;
    }

    RockyServer* thiz = (RockyServer *)malloc(sizeof(RockyServer));
    thiz->thread_count = thread_count;
    thiz->buf_size = buf_size;
    thiz->on_received = on_received;
    thiz->on_disconnected = on_disconnected;
    thiz->thread_pool = server_thread_pool_create(thread_count);
    thiz->main_looper = ALooper_prepare(0);
    thiz->shutdown = 0;
    thiz->server_fd = server_fd;

    return thiz;
}

static int rocky_server_setup_connection(RockyServer* thiz, int socket) {
    //创建一个连接，并派发到线程池中去。
    RockyConnection* connection = rocky_connection_create(socket, thiz->buf_size,
                                                          thiz->on_received, thiz->on_disconnected);
    server_thread_pool_add(thiz->thread_pool, connection);
}

static int rocky_server_on_client_accept(int fd, int events, void* ctx) {
    RockyServer *thiz =(RockyServer *)ctx;
    app_sys_debug("%s accept begin", __func__);
    int socket = accept(thiz->server_fd, NULL, NULL);
    if(socket < 0) {
        app_sys_debug("%s accept failed: %s", __func__, strerror(errno));
        return -1;
    }
    app_sys_debug("%s accept done: %d", __func__, socket);
    return rocky_server_setup_connection(thiz, socket);
}

int rocky_server_loop(RockyServer *thiz) {
    thiz->main_looper = ALooper_prepare(0);
    ALooper_acquire(thiz->main_looper);
    set_non_block(thiz->server_fd);
    ALooper_addFd(thiz->main_looper, thiz->server_fd, 0, ALOOPER_EVENT_INPUT,(ALooper_callbackFunc)rocky_server_on_client_accept, thiz);
    while(!thiz->shutdown) {
        ALooper_pollOnce(DEFAULT_POLL_TIME_MS, NULL, NULL, NULL);
    }
}

void rocky_server_destroy(RockyServer *thiz) {
    if(thiz == NULL) {
        return;
    }
    thiz->shutdown = 1;
    ALooper_wake(thiz->main_looper);
    if(thiz->thread_pool != NULL) {
        server_thread_pool_destroy(thiz->thread_pool);
        thiz->thread_pool = NULL;
    }

    if(thiz->main_looper != NULL) {
        ALooper_removeFd(thiz->main_looper, thiz->server_fd);
        ALooper_release(thiz->main_looper);
        thiz->main_looper = NULL;
    }

    free(thiz);
}